package be.sc.classicnetwork.controller;

import java.io.BufferedOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import be.sc.classicnetwork.dao.PaginationSearchResult;
import be.sc.classicnetwork.exception.ApplicationException;
import be.sc.classicnetwork.model.Car;
import be.sc.classicnetwork.model.Image;
import be.sc.classicnetwork.model.User;
import be.sc.classicnetwork.model.UserLog;
import be.sc.classicnetwork.model.code.Make;
import be.sc.classicnetwork.service.ServiceLocator;
import be.sc.classicnetwork.util.RequestAttributeConstant;

/**
 * Multi Action Controller.
 */
public class ApplicationMultiActionController extends MultiActionController {

    private int maxPageItems;

    private ServiceLocator serviceLocator;

    /**
     * getOffset.
     */
    private int getOffset(HttpServletRequest request) {
	String offset = request.getParameter(RequestAttributeConstant.PAGER_OFFSET);
	return (StringUtils.isEmpty(offset)) ? 0 : Integer.parseInt(offset);
    }

    /**
     * initPager.
     */
    private void initPager(HttpServletRequest request) {
	request.setAttribute(RequestAttributeConstant.PAGE_URL, request.getRequestURI());
	request.setAttribute(RequestAttributeConstant.MAX_PAGE_ITEMS, maxPageItems);
    }

    /**
     * index.
     */
    public ModelAndView index(HttpServletRequest request, HttpServletResponse response) throws Exception {
	return listAllCars(request, response);
    }

    /**
     * home.
     */
    public ModelAndView home(HttpServletRequest request, HttpServletResponse response) throws Exception {
	return new ModelAndView();
    }

    /**
     * getListCarsModelAndView.
     */
    @SuppressWarnings("unchecked")
    private ModelAndView getListCarsModelAndView(PaginationSearchResult result) {
	ModelAndView modelAndView = new ModelAndView("listCars");
	modelAndView.addObject("carList", result.getList());
	modelAndView.addObject("count", result.getCount());

	return modelAndView;
    }

    /**
     * listCarsByMake.
     */
    public ModelAndView listCarsByMake(HttpServletRequest request, HttpServletResponse response) throws Exception {
	initPager(request);
	String id = ServletRequestUtils.getRequiredStringParameter(request, "id");

	boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
	int offset = getOffset(request);
	PaginationSearchResult result = getServiceLocator().getCarService().findByMake(offset, maxPageItems,
		enableFilterPublished, new Make(id));

	return getListCarsModelAndView(result);
    }

    /**
     * listCarsByModel.
     */
    public ModelAndView listCarsByModel(HttpServletRequest request, HttpServletResponse response) throws Exception {
	initPager(request);
	String queryString = ServletRequestUtils.getRequiredStringParameter(request, "model");

	boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
	int offset = getOffset(request);
	PaginationSearchResult result = getServiceLocator().getCarService().findByModelOrMakeLike(offset, maxPageItems,
		enableFilterPublished, queryString);

	return getListCarsModelAndView(result);
    }

    /**
     * listAllCars.
     */
    public ModelAndView listAllCars(HttpServletRequest request, HttpServletResponse response) throws Exception {
	initPager(request);
	boolean enableFilterPublished = !User.getCurrentUser().isAdmin();
	int offset = getOffset(request);
	PaginationSearchResult result = getServiceLocator().getCarService().findAll(offset, maxPageItems,
		enableFilterPublished);

	return getListCarsModelAndView(result);
    }

    /**
     * viewImage.
     */
    public void viewImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
	String id = ServletRequestUtils.getRequiredStringParameter(request, "id");
	String type = ServletRequestUtils.getStringParameter(request, "type");

	Image image = getServiceLocator().getCarService().findImageById(id);

	if (image == null) {
	    return;
	}

	response.setContentType("image/jpeg");

	// use BufferedOutputStream for performance
	BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
	try {
	    // show normal image
	    if (!StringUtils.isEmpty(type)) {
		response.setContentLength(image.getFile().length);
		out.write(image.getFile());
	    }

	    // show thumb
	    else {
		response.setContentLength(image.getThumb().length);
		out.write(image.getThumb());
	    }
	} finally {
	    out.close();
	}

	// don't log viewImage action
	UserLog userLog = (UserLog) request.getAttribute(RequestAttributeConstant.USER_LOG);
	userLog.setPersistable(false);
    }

    /**
     * This method has been created to simulate an ApplicationException.
     */
    public ModelAndView throwException(HttpServletRequest request, HttpServletResponse response) throws Exception {
	throw new ApplicationException("This is an Exception");
    }

    /**
     * login.
     */
    public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
	return new ModelAndView("loginForm");
    }

    /**
     * viewCar.
     */
    public ModelAndView viewCar(HttpServletRequest request, HttpServletResponse response) throws Exception {
	String id = ServletRequestUtils.getRequiredStringParameter(request, "id");

	// get the specified car
	Car car = getServiceLocator().getCarService().findByIdWithFullDependencies(id);

	// log which car has been viewed by the user
	UserLog userLog = (UserLog) request.getAttribute(RequestAttributeConstant.USER_LOG);
	userLog.setCarViewed(car);

	return new ModelAndView().addObject(car);
    }

    /**
     * viewCarImages.
     */
    public ModelAndView viewCarImages(HttpServletRequest request, HttpServletResponse response) throws Exception {
	String id = ServletRequestUtils.getRequiredStringParameter(request, "id");
	return new ModelAndView().addObject("images", getServiceLocator().getCarService().findByIdWithFullDependencies(id).getImages());
    }

    /**
     * buy.
     */
    public ModelAndView buy(HttpServletRequest request, HttpServletResponse response) throws Exception {
	return new ModelAndView();
    }

    /**
     * sell.
     */
    public ModelAndView sell(HttpServletRequest request, HttpServletResponse response) throws Exception {
	return new ModelAndView();
    }

    /**
     * refreshCache.
     */
    public ModelAndView refreshCache(HttpServletRequest request, HttpServletResponse response) throws Exception {
	this.serviceLocator.getCarService().refreshAllCache();
	return new ModelAndView("redirect:/index.html");
    }

    public ServiceLocator getServiceLocator() {
	return serviceLocator;
    }

    public void setServiceLocator(ServiceLocator serviceLocator) {
	this.serviceLocator = serviceLocator;
    }

    public void setMaxPageItems(int maxPageItems) {
	this.maxPageItems = maxPageItems;
    }

}
